﻿using System;

namespace _5种访问修饰符
{
    class Program
    {
        static void Main(string[] args)
        {
            //ALT+ENTER 快速实现提示
            //访问修饰符：
            //1. public : 公开的，可跨类类型访问，可跨程序集访问 ，访问啥：类类型，类中的成员
            //2. private ：私有的，只能在当前类型中访问（class 、struct），命名空间中不能用private （只能用 public 、internal）
            //2.1 private 访问啥：类中的成员 
            //3. protected: 保护的（家族式的行为）， 在当前类型中访问、在继承类中访问 ,修饰类型成员
            //3.1 protected 在类中类可以用在 类类型
            //4. internal ： 只能在同一个程序集访问，不可跨程序集访问 ，修饰的是类类型、类中的成员
            //5. protected internal : 不能在命名空间中对类类型进行修饰 ，类中类 OK
            //5.1 internal (村的保护级别) protected （家族的保护级别），
            //5.2 他俩结合是啥意思：不能跨程序集，能够在继承类中访问，能够在继承类之外访问。

            //public访问修饰符的使用
            A a = new A();
            a.Pub();//公开的，可以跨类类型访问。
            B b = new B("喊喊");
            //B类中的成员被private修饰符修饰，所以外界无法访问。
            b.Priv();
            //protected修饰符的使用
            E e = new E("傻傻");
            e.Ee();
            //internal修饰符的使用
            F f = new F("豆豆");//internal修饰符修饰的可以在本程序集中访问
            f.Ff();
            //internal protected修饰符使用
            G g = new G("逼逼");
            g.Gg();//internal protected 修饰符可以在继承类中访问也可以在外部访问。
            Z z = new Z("66");
            z.Gg();

            
        }
    }
    //类类型默认的访问修饰符是internal：只能在本程序集中访问，不可以跨程序集
    public class A//public 的使用
    {
        public void Pub()
        {
            Console.WriteLine("我是public访问修饰符");
        }
    }
    class B//private protected 无法在命名空间中声明
    {
        private string name;//将name变成public修饰符外界可以访问
        public B(string name)
        {
            this.name = name;
        }
         public void Priv()//外界无法访问,只能在内部使用。
        {
            Console.WriteLine($"我是private访问修饰符的{name}");
        }
        
    }
    class C//:B //C继承B看看可以访问private修饰符的成员吗？
    {
        //继承关系也不可以访问private修饰过的成员
        //D d = new D("ssss");//protected修饰的方法不在继承类中无法访问

    }
    class D//protected 修饰符
    {
        protected string name;
        protected D (string name)
        {
            this.name = name;
        }
         protected void Prot()
        {
            Console.WriteLine($"我是protected修饰符的{name}");
        }
    }
    class E : D//测试protected修饰的子类     可以访问
    { 
        public E(string name):base(name)
        {

        }
      public void Ee()
        {
            this.Prot();//protected修饰符可以在继承类中使用
        }
        
    }
    internal class F //测试internal访问修饰符
    {
        internal string name;
        internal F(string name)
        {
            this.name = name;
        }
        internal void Ff()
        {
            Console.WriteLine($"我是internal修饰符{name}");
        }
    }
     class G//internal protected无法在命名空间声明
    {
        internal protected string name;
        internal protected G(string name)
        {
            this.name = name;
        }
        internal protected void Gg()
        {
            Console.WriteLine($"我是internal protected修饰符的{name}");
        }
    }
    class Z:G
    {
        public Z(string name) : base(name) { }
        
        public void Zz()
        {
            this.Gg();//internal protected访问修饰符也可以在继承类中访问
        }
    }

}
//访问修饰符的其他注意事项：
/*
 * 1. Interface ：抽象成员不能有访问修饰符，方法一旦有访问修饰符就必须实现
 * 2. 枚举的成员不能有访问修饰符,有则导致IDE紊乱
 * 3. 枚举本身在命名空间中不能用 private 等，和 class 规则保持一致。
*/